package com.yanqu.road.server.gameplayer.module.clinic;

import com.yanqu.road.entity.clinic.*;
import com.yanqu.road.entity.config.clinic.ClinicEventInfo;
import com.yanqu.road.entity.config.clinic.DepartmentLv;
import com.yanqu.road.entity.config.clinic.DiseaseInfo;
import com.yanqu.road.entity.config.clinic.PatientInfo;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.config.skill.SkillInfo;
import com.yanqu.road.entity.config.skill.SkillUpgradeInfo;
import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.log.LogClinicCure;
import com.yanqu.road.entity.log.LogClinicDepartment;
import com.yanqu.road.entity.log.LogClinicDisease;
import com.yanqu.road.entity.log.LogClinicEvent;
import com.yanqu.road.entity.messageSubscribe.entity.MessageUserNoticeData;
import com.yanqu.road.entity.task.args.ClinicRankArgs;
import com.yanqu.road.logic.bussiness.player.UserClinicBusiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.helper.CalcPowerResult;
import com.yanqu.road.logic.helper.PowerHelper;
import com.yanqu.road.pb.clinic.ClinicProto;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.gameplayer.module.player.EarnSpeedModule;
import com.yanqu.road.server.gameplayer.module.xiaomian.XiaoMianModule;
import com.yanqu.road.server.manger.activity.ActivityMgr;
import com.yanqu.road.server.manger.activity.NormalActivityMgr;
import com.yanqu.road.server.manger.activity.curio.CurioMgr;
import com.yanqu.road.server.manger.config.ClinicMgr;
import com.yanqu.road.server.manger.config.GoodsMgr;
import com.yanqu.road.server.manger.config.SkillMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.manger.messagesubscribe.MessageSubscribeMgr;
import com.yanqu.road.server.manger.rank.RankMgr;
import com.yanqu.road.server.pb.ClinicPb;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.utils.ListHelper;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author ：zfr
 * @date ：2021/2/24 14:42
 * 医馆模块
 */
public class ClinicModule extends GeneralModule {
    private static Logger logger = LogManager.getLogger(ClinicModule.class.getName());
    private UserClinicData userClinicData;
    private int lastSaveTimePatient = -1;           //上线前最后一次保存的用户医馆数据 用于找回

    public ClinicModule(GamePlayer player) {
        super(player);
    }

    public UserClinicData getUserClinicData() {
        return userClinicData;
    }

    @Override
    public boolean loadData() {
        userClinicData = UserClinicBusiness.getUserClinicData(getUserId());
        if (userClinicData == null) {
            initUserClinicData();
        }
        if (userClinicData != null){
            lastSaveTimePatient = userClinicData.getPatientNum();
        }
        Map<Integer, DepartmentData> departmentDataMap = UserClinicBusiness.getDepartmentDataMap(getUserId());
        userClinicData.setDepartmentMap(departmentDataMap);
        Map<Integer, DiseaseData> diseaseDataMap = UserClinicBusiness.getDiseaseDataMap(getUserId());
        userClinicData.setDiseaseDataMap(diseaseDataMap);
        return true;
    }


    /**
     * 初始化玩家医馆数据
     */
    private void initUserClinicData() {
        userClinicData = new UserClinicData();
        userClinicData.setUserId(getUserId());
        userClinicData.setDepartmentMap(new ConcurrentHashMap<>());
        userClinicData.setUnLockPatientList(ClinicMgr.unLockPatientDefault());
        userClinicData.setWaitGetPatientList(new ArrayList<>());
        userClinicData.setDiseaseDataMap(new ConcurrentHashMap<>());
        userClinicData.setCurEvenId(0);
        userClinicData.setEventNpc(0);
        userClinicData.setWaitGetPatientList(new ArrayList<>());
        userClinicData.setEventCompeteNum(0);
        userClinicData.setPatientClientStates(new ArrayList<>());
        userClinicData.setCuredPatientCount(0L);
        userClinicData.setClinicScore(0L);
        userClinicData.setPatientNum(GameConfig.CLINIC_PATIENT_INIT_LIMIT);
        userClinicData.setLastGetPatientTime(System.currentTimeMillis());
        userClinicData.setLastCuredTime(System.currentTimeMillis());
        userClinicData.setWaitCurePatientList(new ArrayList<>());
        userClinicData.setWaitEventList(new ArrayList<>());
        userClinicData.setRankActivityDataMap(new ConcurrentHashMap<>());
        clearClinicReward();
        userClinicData.setInsertOption();
    }

    /**
     * 解锁科室
     *
     * @param type 科室类型
     * @return ret 结果
     */
    public int unlockDepartment(int type) {
        //系统未解锁
        if (!SystemOpenMgr.systemOpen(player, eSystemId.Clinic.getValue())) {
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }
        //科室已解锁
        if (userClinicData.getDepartmentMap().containsKey(type)) {
            return GameErrorCode.E_DEPARTMENT_IS_UNLOCK;
        }
        DepartmentLv departmentLv = ClinicMgr.getDepartmentLv(type, 0);
        //配置不存在
        if (departmentLv == null) {
            return GameErrorCode.E_DEPARTMENT_CONFIG_NO_FOUND;
        }
        //解锁条件不满足
        try {
            if (userClinicData.getCuredPatientCount() < Integer.parseInt(departmentLv.getUpCost().split("=")[1])) {
                return GameErrorCode.E_DEPARTMENT_UNLOCK_CONDITION_NO_ENOUGH;
            }
        } catch (Exception e) {
            return GameErrorCode.E_DEPARTMENT_CONFIG_NO_FOUND;
        }
        //解锁
        DepartmentData departmentData = new DepartmentData();
        departmentData.setUserId(getUserId());
        departmentData.setType(type);
        departmentData.setLevel(1);
        departmentData.setInsertOption();
        userClinicData.getDepartmentMap().put(type, departmentData);
        AutoLogMgr.add(new LogClinicDepartment(getUserId(), type, 0, 1, departmentLv.getUpCost()));
        //解锁新病症
        DepartmentLv curLv = ClinicMgr.getDepartmentLv(type, departmentData.getLevel());
        if (curLv != null) {
            unLockDisease(curLv);
        }
        syncClinicData();
        return 0;
    }

    /**
     * 科室升级
     * @param type 科室类型
     * @return ret 结果
     */
    public int departmentUpgrade(int type) {
        //科室未解锁
        if (!userClinicData.getDepartmentMap().containsKey(type)) {
            return GameErrorCode.E_DEPARTMENT_IS_LOCK;
        }
        //需所有科室解锁后才可升级
        if (!ListHelper.integerListCompare(new ArrayList<>(userClinicData.getDepartmentMap().keySet()), new ArrayList<>(ClinicMgr.getDepartmentLvMap().keySet()))) {
            return GameErrorCode.E_DEPARTMENT_NOT_ALL_UNLOCK;
        }
        DepartmentData departmentData = userClinicData.getDepartmentMap().get(type);
        int originLv = departmentData.getLevel();
        int upLevel = departmentData.getLevel() + 1;
        DepartmentLv departmentLv = ClinicMgr.getDepartmentLv(type, departmentData.getLevel());
        DepartmentLv upLevelDepartment = ClinicMgr.getDepartmentLv(type, upLevel);
        //科室等级配置未找到 科室已满级
        if (departmentLv == null || upLevelDepartment == null) {
            return GameErrorCode.E_DEPARTMENT_LEVEL_LIMIT;
        }
        //道具不足
        if (!player.getModule(CurrencyModule.class).removeCurrency(PropertyHelper.parseStringToProperty(departmentLv.getUpCost()),
                eLogMoneyType.Clinic, eLogMoneyType.ClinicUpgradeDepartmentCost)) {
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }
        //升级
        userClinicData.getDepartmentMap().get(type).setLevel(upLevel);
        AutoLogMgr.add(new LogClinicDepartment(getUserId(), type, originLv, upLevel, departmentLv.getUpCost()));
        unLockDisease(upLevelDepartment);
        changeClinicValueRank();
        syncClinicData();
        return 0;
    }

    /**
     * 解锁新病症
     * @param departmentLv
     */
    public void unLockDisease(DepartmentLv departmentLv) {
        //解锁新病症 触发事件
        if (departmentLv.getUnlockDiseaseId() > 0) {
            int diseaseId = departmentLv.getUnlockDiseaseId();
            if (!userClinicData.getDiseaseDataMap().containsKey(diseaseId)) {
                DiseaseInfo diseaseInfo = ClinicMgr.getDiseaseInfo(diseaseId);
                DiseaseData diseaseData = new DiseaseData();
                diseaseData.setId(diseaseId);
                diseaseData.setUserId(getUserId());
                diseaseData.setLevel(1);
                diseaseData.setValue(0L);
                diseaseData.setInsertOption();
                userClinicData.getDiseaseDataMap().put(diseaseData.getId(), diseaseData);
                AutoLogMgr.add(new LogClinicDisease(getUserId(), diseaseInfo == null ? 0 : diseaseInfo.getOccupation(),
                        diseaseId, 0, 1, 0));
            }
        }
        if (departmentLv.getEventId() != 0) {
            ClinicEventInfo eventInfo = ClinicMgr.getEventInfo(departmentLv.getEventId());
            if (eventInfo != null) {
                if (userClinicData.getCurEvenId() == 0) {
                    setEvent(eventInfo);
                } else {
                    userClinicData.getWaitEventList().add(eventInfo.getEventId());
                    userClinicData.setUpdateOption();
                }
            }
        }
    }


    /**
     * 病人获得(体力恢复)
     */
    public void getPatient() {
        int patientMax = (int) (userClinicData.getClinicScore() / GameConfig.CLINIC_PATIENT_LIMIT_ADD_SCORE + GameConfig.CLINIC_PATIENT_INIT_LIMIT);
        patientMax = Math.min(patientMax, GameConfig.CLINIC_PATIENT_FINAL_LIMIT);
        CalcPowerResult calcPowerResult = PowerHelper.calcPower(userClinicData.getLastGetPatientTime() / 1000,
                GameConfig.CLINIC_PATIENT_RECOVERY_DURATION, 1, patientMax, userClinicData.getPatientNum());
        userClinicData.setPatientNum(calcPowerResult.getCurPower());
        userClinicData.setLastGetPatientTime(calcPowerResult.getLastRecoverTime() * 1000);
    }

    private void hospitalRecoveryTime(){
        if(!MessageSubscribeMgr.isSwitch()){
            return;
        }
        long nowTime = System.currentTimeMillis();
        long recoveryTime = 0;

        int maxEnergy =  (int) (userClinicData.getClinicScore() / GameConfig.CLINIC_PATIENT_LIMIT_ADD_SCORE + GameConfig.CLINIC_PATIENT_INIT_LIMIT);
        long energyRestoreTime = GameConfig.CLINIC_PATIENT_RECOVERY_DURATION * 1000;
        if(userClinicData.getPatientNum() < maxEnergy){
            recoveryTime = nowTime + energyRestoreTime * (maxEnergy - userClinicData.getPatientNum());
        }
        MessageUserNoticeData noticeData = MessageSubscribeMgr.getUserNoticeData(player.getUserId());
        noticeData.setHospitalTime(recoveryTime);
    }

    /**
     * 接待病人
     * @return
     */
    public void receptPatient(ClinicProto.ReceptPatientRespMsg.Builder respMsg) {
        int checkResult = receptCheck(false);
        if (checkResult != 0) {
            respMsg.setRet(checkResult);
            return;
        }
        if (userClinicData.getCurReceptPatientNum() <= 0) {
            userClinicData.setLastCuredTime(System.currentTimeMillis());
        }
        userClinicData.setCurReceptPatientNum(userClinicData.getCurReceptPatientNum() + 1);
        //当前接待人数不足6人 直接去排队诊断
        randomWaitPatient();
        userClinicData.setPatientNum(userClinicData.getPatientNum() - 1);
        syncClinicData();
        addActivityData(1);
        player.notifyListener(eGamePlayerEventType.ClinicReception.getValue(), 1);
        player.notifyListener(eGamePlayerEventType.ClinicReceptionTimes.getValue(), 1);
        //小面增加任务
        player.getModule(XiaoMianModule.class).addClinicReception(1);
        respMsg.setRet(0);

        //病人存量不足
        if (userClinicData.getPatientNum() <= 0) {
            player.notifyListener(eGamePlayerEventType.RechargeClinicCureCountNew.getValue(), 0);
        }
        try {
            hospitalRecoveryTime();
        }catch (Exception e){
            log.error("error:" + e);
        }
    }

    /**
     * 增加活动冲榜需要计入的病人数
     */
    public void addActivityData(int num) {
        List<Integer> activityIdList = NormalActivityMgr.getOpenClinicRankActivityIdList();
        Map<Integer, RankActivityData> rankActivityDataMap = userClinicData.getRankActivityDataMap();
        synchronized (rankActivityDataMap) {
            for (Integer activityId : activityIdList) {
                if (!ActivityMgr.activityInTime(NormalActivityMgr.getActivityInfo(activityId))) {
                    continue;
                }
                if (!rankActivityDataMap.containsKey(activityId)) {
                    RankActivityData data = new RankActivityData();
                    data.setActivityId(activityId);
                    data.setNeedAddScorePatientNum(0);
                    rankActivityDataMap.put(activityId, data);
                }
                RankActivityData data = rankActivityDataMap.get(activityId);
                data.setNeedAddScorePatientNum(data.getNeedAddScorePatientNum() + num);
                userClinicData.setUpdateOption();
            }
        }
    }

    /**
     * 随机排队病人
     */
    public void randomWaitPatient() {
        int diffValueRecept = userClinicData.getCurReceptPatientNum() - userClinicData.getWaitCurePatientList().size();
        int diffValueLimit = GameConfig.CLINIC_CLINICAL_STAGE_LIMIT - userClinicData.getWaitCurePatientList().size();
        int minValue = Math.min(diffValueRecept, diffValueLimit);
        if (minValue <= 0) {
            return;
        }
        for (int i = 0; i < minValue; i++) {
            userClinicData.setMaxPatientId(userClinicData.getMaxPatientId() + 1);
            userClinicData.getWaitCurePatientList().add(new WaitCurePatient(randomPatient(), randomDisease(), userClinicData.getMaxPatientId()));
        }
        userClinicData.setUpdateOption();
    }

    /**
     * 检查初始化解锁
     * @return
     */
    public boolean checkUnLock() {
        return userClinicData.getDepartmentMap().size() > 0
                && userClinicData.getDiseaseDataMap().size() > 0
                && userClinicData.getUnLockPatientList().size() > 0;
    }

    /**
     * 医馆接待检查
     * @param assistantFlag 是否是小玉助手
     * @return
     */
    public int receptCheck(boolean assistantFlag) {
        getPatient();
        //检查解锁
        if (!checkUnLock()) {
            return GameErrorCode.E_CONDITION_IS_LOCK;
        }
        //病人存量不足
        if (userClinicData.getPatientNum() <= 0) {
            //6.4.0小玉助手不触发现金礼包
            if (!assistantFlag) {
                player.notifyListener(eGamePlayerEventType.RechargeClinicCureCount.getValue(), 0);
                player.notifyListener(eGamePlayerEventType.RechargeClinicCureCountNew.getValue(), 0);
            }
            return GameErrorCode.E_PATIENT_NUM_NO_ENOUGH;
        }
        //接待人数达到上限
        if (userClinicData.getCurReceptPatientNum() >= GameConfig.CLINIC_RECEPTION_LIMIT) {
            return GameErrorCode.E_RECEPTION_LIMIT;
        }
        return 0;
    }

    /**
     * 一键接待病人
     * @param respMsg
     * @param assistantFlag 是否是小玉助手
     */
    public void oneKeyReceptPatient(ClinicProto.ReceptPatientRespMsg.Builder respMsg, boolean assistantFlag) {
        int checkResult = receptCheck(assistantFlag);
        if (checkResult != 0) {
            respMsg.setRet(checkResult);
            return;
        }
        //一键功能未解锁
        if (userClinicData.getCuredPatientCount() < GameConfig.CLINIC_ONE_KEY_RECEPTION_NEED) {
            respMsg.setRet(GameErrorCode.E_ONE_KEY_RECEPT_LOCK);
            return ;
        }
        if (userClinicData.getCurReceptPatientNum() <= 0) {
            userClinicData.setLastCuredTime(System.currentTimeMillis());
        }
        //撸到上限
        int receptNum = userClinicData.getPatientNum();
        if (userClinicData.getPatientNum() + userClinicData.getCurReceptPatientNum() >= GameConfig.CLINIC_RECEPTION_LIMIT) {
            receptNum = GameConfig.CLINIC_RECEPTION_LIMIT - userClinicData.getCurReceptPatientNum();
        }

        if (receptNum < 0) {
            logger.info("receptNum < 0, userId:{}, curReceptNum:{}, receptionLimit:{}", getUserId(), userClinicData.getCurReceptPatientNum(), GameConfig.CLINIC_RECEPTION_LIMIT);
            respMsg.setRet(0);
            return ;
        }
        respMsg.setNum(receptNum);
        userClinicData.setCurReceptPatientNum(userClinicData.getCurReceptPatientNum() + receptNum);
        randomWaitPatient();
        userClinicData.setPatientNum(userClinicData.getPatientNum() - receptNum);
        syncClinicData();
        addActivityData(receptNum);
        player.notifyListener(eGamePlayerEventType.ClinicReception.getValue(), receptNum);
        player.notifyListener(eGamePlayerEventType.ClinicReceptionTimes.getValue(), receptNum);
        //小面增加任务
        player.getModule(XiaoMianModule.class).addClinicReception(receptNum);
        respMsg.setRet(0);

        //病人存量不足
        if (userClinicData.getPatientNum() <= 0) {
            //6.4.0小玉助手不触发现金礼包
            if (!assistantFlag) {
                player.notifyListener(eGamePlayerEventType.RechargeClinicCureCountNew.getValue(), 0);
            }
        }
        try {
            hospitalRecoveryTime();
        }catch (Exception e){
            log.error("error:" + e);
        }
    }

    /**
     * 随机病人
     * @return 病人id
     */
    public int randomPatient() {
        //有新解锁的病人还未刷新 优先获取
        if (userClinicData.getWaitGetPatientList().size() > 0) {
            int patientId = userClinicData.getWaitGetPatientList().get(0);
            userClinicData.getWaitGetPatientList().remove(0);
            return patientId;
        }
        List<PatientInfo> patientInfos = new ArrayList<>();
        for (Integer patientId : userClinicData.getUnLockPatientList()) {
            PatientInfo patientInfo = ClinicMgr.getPatientInfo(patientId);
            if (patientInfo != null) {
                patientInfos.add(patientInfo);
            }
        }
        List<Integer> weightList = new ArrayList<>();
        for (PatientInfo patientInfo : patientInfos) {
            weightList.add(patientInfo.getWeight());
        }
        int index = RandomHelper.getRandomIndexByWeight(weightList, new Random());
        return patientInfos.get(index).getPatientId();
    }

    /**
     * 病人解锁
     * @param patientId 病人id
     * @return
     */
    public int unLockPatient(int patientId) {
        //已解锁
        if (userClinicData.getUnLockPatientList().contains(patientId)) {
            return GameErrorCode.E_PATIENT_IS_UNLOCK;
        }
        PatientInfo patientInfo = ClinicMgr.getPatientInfo(patientId);
        //病人配置未找到
        if (patientInfo == null) {
            return GameErrorCode.E_PATIENT_CONFIG_NO_FOUND;
        }
        //医馆评分不足以解锁病人
        if (userClinicData.getClinicScore() < patientInfo.getUnlockScore()) {
            return GameErrorCode.E_PATIENT_UNLOCK_CONDITION_NO_ENOUGH;
        }
        //检查前置的病人是否已经解锁
        int lastPatientId = ClinicMgr.getLastPatientId(patientId);
        if (lastPatientId != patientId && !userClinicData.getUnLockPatientList().contains(lastPatientId)) {
            return GameErrorCode.E_LAST_PATIENT_IS_LOCK;
        }
        //解锁病人
        userClinicData.getUnLockPatientList().add(patientId);
        //新解锁未刷新的病人id
        userClinicData.getWaitGetPatientList().add(patientId);
        userClinicData.setUpdateOption();
        syncClinicData();
        return 0;
    }

    /**
     * 检查病人诊断状态
     * @return
     */
    public int checkPatientCureState(long id) {
        if (userClinicData.getWaitCurePatientList().size() > 0) {
            if (userClinicData.getWaitCurePatientList().get(0).getId() < id) {
                return GameErrorCode.E_CLINIC_CURE_EXCEPTION;
            } else if (userClinicData.getWaitCurePatientList().get(0).getId() == id) {
                return 0;
            }
        }
        return GameErrorCode.E_CLINIC_PATIENT_IS_CURED;
    }

    /**
     * 治疗病人(诊断)
     * @return
     */
    public int curePatient(boolean online, long id) {
        //检查解锁
        if (!checkUnLock()) {
            return GameErrorCode.E_CONDITION_IS_LOCK;
        }
        if (online) {
            //在线诊断检查一下病人的诊断状态
            int ret = checkPatientCureState(id);
            if (ret != 0) {
                return ret;
            }
        }
        //没病人在接待中
        if (userClinicData.getCurReceptPatientNum() <= 0) {
            return GameErrorCode.E_PATIENT_NO_PATIENT;
        }
        //诊断时间间隔限制
        if (online && System.currentTimeMillis() - userClinicData.getLastCuredTime() < 5 * DateHelper.SECOND_MILLIONS) {
            return GameErrorCode.E_CLINIC_CURE_TIME_EXCEPTION;
        }
        //获取当前治疗的病人(排列的第一个)
        WaitCurePatient waitCurePatient = userClinicData.getWaitCurePatientList().get(0);

        LogClinicCure cureLog = new LogClinicCure(getUserId(), waitCurePatient.getPatientId(), waitCurePatient.getDiseaseId(), "", 0, 0, 0, userClinicData.getCurEvenId());

        if (userClinicData.getDiseaseDataMap().containsKey(waitCurePatient.getDiseaseId())) {
            //计算收益
            if (userClinicData.getDiseaseDataMap().containsKey(waitCurePatient.getDiseaseId())) {
                List<Integer> addScoreActivityIds = new ArrayList<>();
                Map<Integer, RankActivityData> rankActivityDataMap = userClinicData.getRankActivityDataMap();
                for (RankActivityData rankActivityData : rankActivityDataMap.values()) {
                    if (rankActivityData.getNeedAddScorePatientNum() >= userClinicData.getCurReceptPatientNum()
                        && ActivityMgr.activityInTime(NormalActivityMgr.getActivityInfo(rankActivityData.getActivityId()))) {
                        addScoreActivityIds.add(rankActivityData.getActivityId());
                    }
                }
                getCureReward(waitCurePatient.getDiseaseId(), waitCurePatient.getPatientId(), cureLog, addScoreActivityIds);
                //治愈病人数量加一
                userClinicData.setCuredPatientCount(userClinicData.getCuredPatientCount() + 1);
                player.notifyListener(eGamePlayerEventType.ClinicTotalReception.getValue(), userClinicData);
            }
            //当前事件完成数累加
            if (userClinicData.getCurEvenId() > 0) {
                ClinicEventInfo eventInfo = ClinicMgr.getEventInfo(userClinicData.getCurEvenId());
                if (eventInfo != null && eventInfo.getDiseaseId() == waitCurePatient.getDiseaseId()) {
                    userClinicData.setEventCompeteNum(userClinicData.getEventCompeteNum() + 1);
                }
            }
        }
        //当前接待病人数量减一
        userClinicData.setCurReceptPatientNum(userClinicData.getCurReceptPatientNum() - 1);
        //移除第一个排队诊断的人
        userClinicData.getWaitCurePatientList().remove(0);
        //最后n个病人的诊断信息加入 n = 5
        addLastNPatientCureInfo(waitCurePatient);
        //随机病人 加入等待诊断排队列表
        randomWaitPatient();
        if (online) {
            //设置最后诊断时间
            userClinicData.setLastCuredTime(System.currentTimeMillis());
            syncClinicData();
        }
        AutoLogMgr.add(cureLog);
        return 0;
    }

    /**
     * 随机病症
     * 是否还有未解锁病症 -> 是否是未解锁病症 -> 是否存在事件未完成 -> 计算随机权重 -> 随机病症
     * @return
     */
    private int randomDisease() {
        List<Integer> lockDiseaseList = new ArrayList<>();
        for (DepartmentData data : userClinicData.getDepartmentMap().values()) {
            int diseaseId = ClinicMgr.getFirstLockDisease(data.getType(), data.getLevel());
            if (diseaseId != 0) {
                lockDiseaseList.add(diseaseId);
            }
        }
        Random random = new Random();
        int randomInt = random.nextInt(1000);
        //是否是未解锁病症
        if (randomInt < GameConfig.CLINIC_LOCK_DISEASE_RANDOM && lockDiseaseList.size() > 0) {
            //随机未解锁病症
            List<Integer> weightList = new ArrayList<>();
            for (Integer id : lockDiseaseList) {
                weightList.add(ClinicMgr.getDiseaseInfo(id).getWeight());
            }
            int index = RandomHelper.getRandomIndexByWeight(weightList, new Random());
            return lockDiseaseList.get(index);
        } else {
            //随机已解锁病症
            //存在特殊事件
            ClinicEventInfo eventInfo = null;
            boolean isEventDisease = false;
            if (userClinicData.getCurEvenId() != 0) {
                eventInfo = ClinicMgr.getEventInfo(userClinicData.getCurEvenId());
                if (eventInfo != null && userClinicData.getEventCompeteNum() < eventInfo.getNeedCureNum()) {
                    //随机事件对应的病症权重
                    int randomWeight = new Random().nextInt(1000);
                    if (randomWeight < eventInfo.getDiseaseWeight()) {
                        isEventDisease = true;
                    }
                }
            }
            int diseaseId;
            //特殊事件概率触发对应病症
            if (isEventDisease) {
                diseaseId = eventInfo.getDiseaseId();
            } else {
                //按权重随机病症
                List<DiseaseData> diseaseDataList = new ArrayList<>(userClinicData.getDiseaseDataMap().values());
                List<Integer> weightList = new ArrayList<>();
                for (DiseaseData diseaseData : diseaseDataList) {
                    weightList.add(ClinicMgr.getDiseaseInfo(diseaseData.getId()).getWeight());
                }
                int index = RandomHelper.getRandomIndexByWeight(weightList, new Random());
                diseaseId = diseaseDataList.get(index).getId();
            }
           return diseaseId;
        }
    }

    /**
     * 加入最后n个病人的诊断信息(顺序由远到近)
     * @param waitCurePatient
     */
    private void addLastNPatientCureInfo(WaitCurePatient waitCurePatient) {
        if (userClinicData.getPatientClientStates().size() >= GameConfig.CLINIC_LAST_N_PATIENT_DISPLAY) {
            userClinicData.getPatientClientStates().remove(0);
        }
        PatientClientState state = new PatientClientState();
        state.setDiseaseId(waitCurePatient.getDiseaseId());
        state.setPatientId(waitCurePatient.getPatientId());
        state.setLastSendTime(System.currentTimeMillis());
        state.setId(waitCurePatient.getId());
        userClinicData.getPatientClientStates().add(state);
        userClinicData.setUpdateOption();
    }

    /**
     * 计算治疗收益(诊断)
     * @param diseaseId
     * @param patientId
     * @param cureLog
     * @param addScoreActivityIds
     */
    public void getCureReward(int diseaseId, int patientId, LogClinicCure cureLog, List<Integer> addScoreActivityIds) {
        PatientInfo patientInfo = ClinicMgr.getPatientInfo(patientId);
        if (patientInfo == null) {
            logger.error("getCureReward error, patientInfo no found, userId:{}, patientId:{}", getUserId(), patientId);
            return;
        }
        //随机获得图纸
        DiseaseInfo diseaseInfo = ClinicMgr.getDiseaseInfo(diseaseId);
        if (diseaseInfo == null) {
            logger.error("getCureReward error, diseaseInfo no found, userId:{}, diseaseId:{}", getUserId(), diseaseId);
            return;
        }
        try {
            String logDepartmentInfo = "";
            String departmentList = diseaseInfo.getDepartmentList();
            for (String s : departmentList.split(";")) {
                int lv = 0;
                if (userClinicData.getDepartmentMap().containsKey(Integer.parseInt(s))) {
                    lv = userClinicData.getDepartmentMap().get(Integer.parseInt(s)).getLevel();
                }
                logDepartmentInfo += s + ":" + lv + ";";
            }
            cureLog.setDepartmentInfo(logDepartmentInfo);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }

        String reward = randomSpecialRewards(diseaseInfo.getRewardWeight());
        if (!reward.isEmpty()) {
            Property good = PropertyHelper.parseStringToProperty(reward);
            //放入聚宝盆
            userClinicData.getClinicRewardData().getReward().addProperty(good);
            cureLog.setGoodNum(good.getCountByGoodsId(110144).intValue());
        }
        //获得医术值
        long value = calcDiseaseValueReward(diseaseInfo, patientInfo);
        cureLog.setValue(value);
        //加入聚宝盆
        Map<Integer, DiseaseReward> diseaseRewardMap = userClinicData.getClinicRewardData().getDiseaseRewardMap();
        if (!diseaseRewardMap.containsKey(diseaseId)) {
            DiseaseReward diseaseReward = new DiseaseReward();
            diseaseReward.setId(diseaseId);
            diseaseReward.setNum(0);
            diseaseReward.setValue(0L);
            diseaseRewardMap.put(diseaseId, diseaseReward);
        }
        diseaseRewardMap.get(diseaseId).setNum(diseaseRewardMap.get(diseaseId).getNum() + 1);
        diseaseRewardMap.get(diseaseId).setValue(diseaseRewardMap.get(diseaseId).getValue() + value);
        //医馆评分 加入聚宝盆
        int addScore = calcDiseaseScore(diseaseInfo);
        userClinicData.getClinicRewardData().setClinicScore(
                userClinicData.getClinicRewardData().getClinicScore() + addScore
        );
        for (Integer activityId : addScoreActivityIds) {
            RankActivityData rankActivityData = userClinicData.getRankActivityDataMap().get(activityId);
            rankActivityData.setScore(rankActivityData.getScore() + addScore);
        }
        cureLog.setScore(addScore);

        userClinicData.getClinicRewardData().setRewardNum(
                userClinicData.getClinicRewardData().getRewardNum() + 1);
    }

    /**
     * 计算病症治疗获得的医馆评分
     * @param diseaseInfo
     * @return
     */
    private int calcDiseaseScore(DiseaseInfo diseaseInfo) {
        int score = 0;
        String departmentList = diseaseInfo.getDepartmentList();
        try {
            String[] split = departmentList.split(";");
            for (String typeStr : split) {
                int type = Integer.parseInt(typeStr);
                if (userClinicData.getDepartmentMap().containsKey(type)) {
                    DepartmentLv departmentLv = ClinicMgr.getDepartmentLv(type, userClinicData.getDepartmentMap().get(type).getLevel());
                    if (departmentLv != null) {
                        score += departmentLv.getScore();
                    }
                }
            }
            long addition = CurioMgr.getSkillAdditionBySkillType(eSkillType.ClinicScoreSkill.getValue(), player, 0);
            score = BigDecimal.valueOf(score).multiply(BigDecimal.valueOf(1000 + addition)).divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_UP).intValue();
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
        }
        return score;
    }

    /**
     * 计算病症医术值收益
     * @param diseaseInfo
     * @param patientInfo
     * @return
     */
    public Long calcDiseaseValueReward(DiseaseInfo diseaseInfo, PatientInfo patientInfo) {
        long value = 0L;
        String departmentList = diseaseInfo.getDepartmentList();
        String[] split = departmentList.split(";");
        //经过科室累加医术值
        for (String departmentTypeStr : split) {
            int departmentType = Integer.parseInt(departmentTypeStr);
            if (userClinicData.getDepartmentMap().containsKey(departmentType)) {
                int level = userClinicData.getDepartmentMap().get(departmentType).getLevel();
                DepartmentLv departmentLv = ClinicMgr.getDepartmentLv(departmentType, level);
                if (departmentLv != null) {
                    value += departmentLv.getValue();
                }
            }
        }
        //病人加成
        value = value * (1000 + patientInfo.getValueAdd()) / 1000;
        return value;
    }

    /**
     * 随机图纸收益
     * @param specialRewards
     * @return
     */
    public String randomSpecialRewards(String specialRewards) {
        try {
            List<String> rewards = new ArrayList<>();
            List<Integer> weight = new ArrayList<>();
            String[] split = specialRewards.split("\\|");
            for (String s : split) {
                String[] split1 = s.split(";");
                rewards.add(split1[0]);
                weight.add(Integer.parseInt(split1[1]));
            }
            int index = RandomHelper.getRandomIndexByWeight(weight, new Random());
            if (rewards.get(index).equals("0")) {
                return "";
            } else {
                return rewards.get(index);
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return "";
        }
    }

    /**
     * 完成事件 领取奖励
     *
     * @return
     * @param respMsg
     */
    public int getEventReward(ClinicProto.GetEventRewardRespMsg.Builder respMsg) {
        //事件是否完成
        if (userClinicData.getCurEvenId() <= 0) {
            return GameErrorCode.E_NO_SPECIAL_EVENT_CUR;
        }
        ClinicEventInfo eventInfo = ClinicMgr.getEventInfo(userClinicData.getCurEvenId());
        if (eventInfo == null) {
            return GameErrorCode.E_EVENT_CONFIG_NO_FOUND;
        }
        if (userClinicData.getEventCompeteNum() < eventInfo.getNeedCureNum()) {
            return GameErrorCode.E_EVENT_IS_UNCOMPETE;
        }
        //清空事件
        userClinicData.setCurEvenId(0);
        userClinicData.setEventCompeteNum(0);
        userClinicData.setEventNpc(0);
        //获得奖励
        player.getModule(CurrencyModule.class).addCurrency(PropertyHelper.parseStringToProperty(eventInfo.getReward()),
                eLogMoneyType.Clinic, eLogMoneyType.ClinicEventReward);
        respMsg.setReward(eventInfo.getReward());
        syncClinicData();
        //如果有等待事件 触发第一个等待的事件
        if (userClinicData.getWaitEventList().size() > 0) {
            ClinicEventInfo nextEventInfo = ClinicMgr.getEventInfo(userClinicData.getWaitEventList().get(0));
            if (nextEventInfo != null) {
                setEvent(nextEventInfo);
                userClinicData.getWaitEventList().remove(0);
                userClinicData.setUpdateOption();
            }
            syncClinicData();
        }
        return 0;
    }

    /**
     * 触发事件
     * @param eventInfo
     */
    public void setEvent(ClinicEventInfo eventInfo) {
        userClinicData.setCurEvenId(eventInfo.getEventId());
        userClinicData.setEventNpc(eventInfo.getNpcType());
        AutoLogMgr.add(new LogClinicEvent(getUserId(), eventInfo.getEventId()));
    }

    /**
     * 病症升级
     * @param diseaseId 病症id
     * @return
     */
    public int upgradeDisease(int diseaseId) {
        DiseaseData diseaseData = userClinicData.getDiseaseDataMap().get(diseaseId);
        if (diseaseData == null) {
            return GameErrorCode.E_DISEASE_IS_LOCK;
        }
        DiseaseInfo diseaseInfo = ClinicMgr.getDiseaseInfo(diseaseId);
        if (diseaseInfo == null) {
            return GameErrorCode.E_DISEASE_CONFIG_NO_FOUND;
        }
        SkillInfo skillInfo = SkillMgr.getSkillInfo(diseaseInfo.getSkill());
        if (skillInfo == null) {
            return GameErrorCode.E_DISEASE_SKILL_CONFIG_NO_FOUND;
        }
        if (skillInfo.getMaxLevel() <= diseaseData.getLevel()) {
            return GameErrorCode.E_DISEASE_SKILL_MAX_LEVEL;
        }
        SkillUpgradeInfo skillUpgradeInfo = SkillMgr.getSkillUpgradeInfo(skillInfo.getUpgradeType(0), diseaseData.getLevel());
        if (skillUpgradeInfo == null) {
            return GameErrorCode.E_DISEASE_SKILL_UPGRADE_NO_FOUND;
        }
        if (diseaseData.getValue() < skillUpgradeInfo.getConsumeCount()) {
            return GameErrorCode.E_DISEASE_VALUE_IS_NO_ENOUGH;
        }
        //满足 扣医术值 升级
        int originLv = diseaseData.getLevel();
        int upLv = diseaseData.getLevel() + 1;
        diseaseData.setValue(diseaseData.getValue() - skillUpgradeInfo.getConsumeCount());
        diseaseData.setLevel(upLv);
        syncClinicData();
        //同步商铺赚速
        player.getModule(EarnSpeedModule.class).scheduleAddSilver();
        AutoLogMgr.add(new LogClinicDisease(getUserId(), diseaseInfo.getOccupation(),
                diseaseId, originLv, upLv, skillUpgradeInfo.getConsumeCount()));
        return 0;
    }

    /**
     * 病症升级（一键升级所有到最高）
     */
    public int upgradeDiseaseOneKey() {

        ClinicProto.UpgradeDiseaseOneKeyRespMsg.Builder respMsg = ClinicProto.UpgradeDiseaseOneKeyRespMsg.newBuilder();
        respMsg.setRet(0);
        for (Map.Entry<Integer, DiseaseData> dataEntry : userClinicData.getDiseaseDataMap().entrySet()) {
            DiseaseData diseaseData = dataEntry.getValue();
            DiseaseInfo diseaseInfo = ClinicMgr.getDiseaseInfo(diseaseData.getId());
            if(diseaseInfo == null){
                ClinicMgr.getLogger().info("病症{}配置未找到，玩家{}", diseaseData.getId(), player.getUserId());
                continue;
            }
            SkillInfo skillInfo = SkillMgr.getSkillInfo(diseaseInfo.getSkill());
            if(skillInfo == null){
                ClinicMgr.getLogger().info("病症{}, 技能{} 配置未找到，玩家{}", diseaseData.getId(), diseaseInfo.getSkill(), player.getUserId());
                continue;
            }
            if (skillInfo.getMaxLevel() <= diseaseData.getLevel()) {
                continue;
            }
            int oldLv = diseaseData.getLevel();
            int addLv = 0;
            long totalCost = 0L;
            for (int i = oldLv; i < skillInfo.getMaxLevel(); i++) {
                SkillUpgradeInfo skillUpgradeInfo = SkillMgr.getSkillUpgradeInfo(skillInfo.getUpgradeType(0), i);
                if(skillUpgradeInfo == null){
                    break;
                }
                if(diseaseData.getValue() < totalCost + skillUpgradeInfo.getConsumeCount()){
                    break;
                }
                totalCost += skillUpgradeInfo.getConsumeCount();
                addLv++;
            }
            if(addLv > 0 && totalCost > 0){
                //满足 扣医术值 升级
                diseaseData.setValue(diseaseData.getValue() - totalCost);
                diseaseData.setLevel(diseaseData.getLevel() + addLv);
                AutoLogMgr.add(new LogClinicDisease(getUserId(), diseaseInfo.getOccupation(),
                        diseaseData.getId(), oldLv, diseaseData.getLevel(), totalCost));

                //
                ClinicProto.UpgradeDiseaseOneKeyResultTemp.Builder result = ClinicProto.UpgradeDiseaseOneKeyResultTemp.newBuilder();
                result.setDiseaseId(diseaseData.getId());
                result.setOldLv(oldLv);
                result.setNowLv(diseaseData.getLevel());
                respMsg.addResult(result);
            }
        }

        if(respMsg.getResultCount() > 0) {
            syncClinicData();
            //同步商铺赚速
            player.getModule(EarnSpeedModule.class).scheduleAddSilver();
        }else {
            respMsg.setRet(GameErrorCode.E_DISEASE_VALUE_IS_NO_ENOUGH);
        }

        player.sendPacket(ClientProtocol.U_CLINIC_UPGRADE_DISEASE_ONE_KEY, respMsg);
        return 0;
    }

    /**
     * 离线治疗
     */
    public void offlineCure() {
        long offCureBeginCostTime = GameConfig.CLINIC_OFFLINE_CURE_BEGIN_TIME * 1000;
        long lastCureTime = userClinicData.getLastCuredTime();
        long durTime = System.currentTimeMillis() - lastCureTime;
        if (durTime <= offCureBeginCostTime) {
            syncClinicData();
            return;
        }
        long curReceptPatientNum = userClinicData.getCurReceptPatientNum();
        int cureNum = (int) (ClinicMgr.calcOffLineCureCount(curReceptPatientNum, (durTime - offCureBeginCostTime) / DateHelper.SECOND_MILLIONS, GameConfig.CLINIC_OFFLINE_CURE_COST_TIME));
        int realCureNum = 0;
        for (int i = 0; i < cureNum; i++) {
            if (curePatient(false, 0L) == 0) {
                realCureNum++;
            } else {
                break;
            }
        }
        if (realCureNum < cureNum || curReceptPatientNum == 0) {
            userClinicData.setLastCuredTime(System.currentTimeMillis());
        } else if (realCureNum > 0) {
            userClinicData.setLastCuredTime(offCureBeginCostTime + ClinicMgr.calcOffLineCureCostTime(curReceptPatientNum, realCureNum, GameConfig.CLINIC_OFFLINE_CURE_COST_TIME) * DateHelper.SECOND_MILLIONS + lastCureTime);
        }
        syncClinicData();
    }

    /**
     * 榜单变更
     */
    public void changeClinicValueRank() {
        try {
            RankMgr.changeUserRank(eBigRankType.Normal.getValue(), player.getUserId(), BigInteger.valueOf(userClinicData.getClinicScore()), eRankType.ClinicValue.getValue(), "");
        } catch (Exception ex) {
            log.error(ex);
        }
    }

    /**
     * 领取聚宝盆奖励
     */
    public int getClinicReward() {
        ClinicRewardData clinicRewardData = userClinicData.getClinicRewardData();
        if (clinicRewardData.getClinicScore() == 0 && clinicRewardData.getReward().isNothing()
                && clinicRewardData.getDiseaseRewardMap().size() == 0) {
            return GameErrorCode.E_CLINIC_NO_REWARD;
        }
        clearClinicReward();
        for (Map.Entry<Integer, DiseaseReward> entry : clinicRewardData.getDiseaseRewardMap().entrySet()) {
            DiseaseData diseaseData = userClinicData.getDiseaseDataMap().get(entry.getKey());
            if (diseaseData != null) {
                //增加病症医术值
                diseaseData.setValue(entry.getValue().getValue() + diseaseData.getValue());
            } else {
                logger.error("reward diseaseId no found,userId:{}, diseaseId:{}", getUserId(), entry.getKey());
            }
        }
        userClinicData.setClinicScore(userClinicData.getClinicScore() + clinicRewardData.getClinicScore());
        player.getModule(CurrencyModule.class).addCurrency(clinicRewardData.getReward(), eLogMoneyType.Clinic, eLogMoneyType.ClinicCureReward);
        ClinicRankArgs clinicRankArgs = new ClinicRankArgs(userClinicData.getRankActivityDataMap());
        player.notifyListener(eGamePlayerEventType.ClinicScoreRiseRank.getValue(), clinicRankArgs);
        player.notifyListener(eGamePlayerEventType.ClinicScore.getValue(), userClinicData.getClinicScore());
        player.notifyListener(eGamePlayerEventType.ClinicScoreAdd.getValue(), clinicRewardData.getClinicScore());
        changeClinicValueRank();
        syncClinicData();
        return 0;
    }

    private void clearClinicReward() {
        ClinicRewardData clinicRewardData = new ClinicRewardData();
        clinicRewardData.setClinicScore(0L);
        clinicRewardData.setRewardNum(0);
        clinicRewardData.setDiseaseRewardMap(new ConcurrentHashMap<>());
        clinicRewardData.setReward(new Property());
        userClinicData.setClinicRewardData(clinicRewardData);
    }

    /**
     * 医馆数据同步
     */
    public void syncClinicData() {
        getPatient();
        fixWaitList();
        ClinicProto.ClinicDataSync.Builder respMsg = ClinicPb.parseClinicData(userClinicData);
        player.sendPacket(ClientProtocol.U_CLINIC_DATA_SYNC, respMsg);
    }

    /**
     * 修复排队列表
     */
    public void fixWaitList() {
        int waitCount = userClinicData.getWaitCurePatientList().size();
        int curReceptNum = userClinicData.getCurReceptPatientNum();
        if (curReceptNum > waitCount && waitCount < GameConfig.CLINIC_CLINICAL_STAGE_LIMIT) {
            logger.error("fix wait list, userId:{}, curReceptNum:{}, waitCount:{}, limit:{}", getUserId(), curReceptNum, waitCount, GameConfig.CLINIC_CLINICAL_STAGE_LIMIT);
            logger.error(Thread.currentThread().getStackTrace()[3]);
        } else if (curReceptNum < waitCount) {
            logger.error("fix curReceptNum, userId:{}, curReceptNum:{}, waitCount:{}, limit:{}", getUserId(), curReceptNum, waitCount, GameConfig.CLINIC_CLINICAL_STAGE_LIMIT);
            logger.error(Thread.currentThread().getStackTrace()[3]);
        }
    }

    /**
     * 获取当前事件详情
     */
    public void getCurEventInfo() {
        ClinicProto.GetCurEventRespMsg.Builder respMsg = ClinicProto.GetCurEventRespMsg.newBuilder();
        respMsg.setEventId(userClinicData.getCurEvenId());
        respMsg.setNum(userClinicData.getEventCompeteNum());
        player.sendPacket(ClientProtocol.U_CLINIC_GET_CUR_EVENT, respMsg);
    }

    /**
     * 获取聚宝盆奖励列表
     * @param respMsg
     */
    public void getClinicRewardList(ClinicProto.GetClinicRewardListRespMsg.Builder respMsg) {
        ClinicRewardData clinicRewardData = userClinicData.getClinicRewardData();
        if (clinicRewardData.getClinicScore() == 0 && clinicRewardData.getReward().isNothing()
                && clinicRewardData.getDiseaseRewardMap().size() == 0) {
            respMsg.setRet(GameErrorCode.E_CLINIC_NO_REWARD);
            return;
        }
        ClinicPb.parseClinicReward(clinicRewardData, respMsg);
    }

    /**
     * 使用病人手册
     * @param count
     * @return
     */
    public int useClinicPatientAddItem(int count) {
        if (count <= 0) {
            return GameErrorCode.E_USE_ITEM_NUM_ERROR;
        }
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(GameConfig.CLINIC_ADD_PATIENT_ITEM);
        if (goodsInfo == null) {
            return GameErrorCode.E_CLINIC_ITEM_CONFIG_NO_FOUND;
        }
        if (!player.getModule(CurrencyModule.class).removeCurrency(new Property(GameConfig.CLINIC_ADD_PATIENT_ITEM, BigInteger.valueOf(count)),
                eLogMoneyType.Clinic, eLogMoneyType.ClinicUseItemCost)) {
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }
        getPatient();
        userClinicData.setPatientNum(userClinicData.getPatientNum() + (goodsInfo.getParamList().get(0).intValue() * count));
        syncClinicData();
        try {
            hospitalRecoveryTime();
        }catch (Exception e){
            log.error("error:" + e);
        }
        return 0;
    }


    @Override
    public boolean afterLoadData() {
        return true;
    }

    @Override
    public boolean saveData() {
        if (userClinicData != null) {
            for (DepartmentData departmentData : userClinicData.getDepartmentMap().values()) {
                if (departmentData.isInsertOption()) {
                    UserClinicBusiness.addDepartmentData(departmentData);
                } else if (departmentData.isUpdateOption()) {
                    UserClinicBusiness.updateDepartmentData(departmentData);
                }
            }

            for (DiseaseData diseaseData : userClinicData.getDiseaseDataMap().values()) {
                if (diseaseData.isInsertOption()) {
                    UserClinicBusiness.addDiseaseData(diseaseData);
                } else if (diseaseData.isUpdateOption()) {
                    UserClinicBusiness.updateDiseaseData(diseaseData);
                }
            }

            if (userClinicData.isInsertOption()) {
                UserClinicBusiness.addUserClinicData(userClinicData);
            } else if (userClinicData.isUpdateOption()) {
                UserClinicBusiness.updateUserClinicData(userClinicData);
            }
        }
        return true;
    }

    @Override
    public void afterLogin() {
        syncClinicData();
        //登陆后移除已过期的活动数据
        Map<Integer, RankActivityData> rankActivityDataMap = userClinicData.getRankActivityDataMap();
        if (rankActivityDataMap == null) {
            return;
        }
        synchronized (rankActivityDataMap) {
            List<Integer> needRemoveList = new ArrayList<>();
            for (RankActivityData activityData : rankActivityDataMap.values()) {
                List<Integer> activityIdList = NormalActivityMgr.getOpenClinicRankActivityIdList();
                if (!activityIdList.contains(activityData.getActivityId())) {
                    needRemoveList.add(activityData.getActivityId());
                }
            }
            if (needRemoveList.size() > 0) {
                for (Integer activityId : needRemoveList) {
                    rankActivityDataMap.remove(activityId);
                }
                userClinicData.setUpdateOption();
            }
        }
    }

    @Override
    public void loginSendMsg() {

    }

    /**
     * 找回医馆病人招待 策划说不能排队 不能加奖励到盆子里 不能影响冲榜 只要奖励
     *
     * @param times
     * @return
     */

    public ClinicProto.GetClinicRewardListRespMsg.Builder recoveryClinicReward(int times) {
        ClinicProto.GetClinicRewardListRespMsg.Builder builder = ClinicProto.GetClinicRewardListRespMsg.newBuilder();

        long recoveryClinicScore = 0L;       //医馆评分
        Map<Integer, DiseaseReward> diseaseRewardMap = new ConcurrentHashMap<>();   //病症 医术值
        Property specialRewards = new Property();               //图纸

        List<WaitCurePatient> patientList = new ArrayList<>();
        if (userClinicData.getDiseaseDataMap() == null || userClinicData.getDiseaseDataMap().isEmpty()){
            builder.setRet(GameErrorCode.E_DEPARTMENT_IS_LOCK);
            return builder;
        }
        for (int i = 0; i < times; i++) {
            WaitCurePatient waitCurePatient = new WaitCurePatient(randomPatient(), randomDisease(), userClinicData.getMaxPatientId());
            patientList.add(waitCurePatient);
        }

        for (WaitCurePatient waitCurePatient : patientList) {
            LogClinicCure cureLog = new LogClinicCure(getUserId(), waitCurePatient.getPatientId(), waitCurePatient.getDiseaseId(), "", 0, 0, 0, userClinicData.getCurEvenId());
            //治愈病人数量加一
            userClinicData.setCuredPatientCount(userClinicData.getCuredPatientCount() + 1);


            PatientInfo patientInfo = ClinicMgr.getPatientInfo(waitCurePatient.getPatientId());
            if (patientInfo == null) {
                logger.error("getCureReward error, patientInfo no found, userId:{}, patientId:{}", getUserId(), waitCurePatient.getPatientId());
                return null;
            }
            //随机获得图纸
            DiseaseInfo diseaseInfo = ClinicMgr.getDiseaseInfo(waitCurePatient.getDiseaseId());
            if (diseaseInfo == null) {
                logger.error("getCureReward error, diseaseInfo no found, userId:{}, diseaseId:{}", getUserId(), waitCurePatient.getPatientId());
                return null;
            }
            try {
                String logDepartmentInfo = "";
                String departmentList = diseaseInfo.getDepartmentList();
                for (String s : departmentList.split(";")) {
                    int lv = 0;
                    if (userClinicData.getDepartmentMap().containsKey(Integer.parseInt(s))) {
                        lv = userClinicData.getDepartmentMap().get(Integer.parseInt(s)).getLevel();
                    }
                    logDepartmentInfo += s + ":" + lv + ";";
                }
                cureLog.setDepartmentInfo(logDepartmentInfo);
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
            String reward = randomSpecialRewards(diseaseInfo.getRewardWeight());
            if (!reward.isEmpty()) {
                Property good = PropertyHelper.parseStringToProperty(reward);
                //放入记录中
                specialRewards.addProperty(good);
                cureLog.setGoodNum(good.getCountByGoodsId(110144).intValue());
            }
            long value = calcDiseaseValueReward(diseaseInfo, patientInfo);
            cureLog.setValue(value);
            if (!diseaseRewardMap.containsKey(waitCurePatient.getDiseaseId())) {
                DiseaseReward diseaseReward = new DiseaseReward();
                diseaseReward.setId(waitCurePatient.getDiseaseId());
                diseaseReward.setNum(0);
                diseaseReward.setValue(0L);
                diseaseRewardMap.put(waitCurePatient.getDiseaseId(), diseaseReward);
            }
            diseaseRewardMap.get(waitCurePatient.getDiseaseId()).setNum(diseaseRewardMap.get(waitCurePatient.getDiseaseId()).getNum() + 1);
            diseaseRewardMap.get(waitCurePatient.getDiseaseId()).setValue(diseaseRewardMap.get(waitCurePatient.getDiseaseId()).getValue() + value);

            int addScore = calcDiseaseScore(diseaseInfo);
            recoveryClinicScore += addScore;
            cureLog.setScore(addScore);

//            //当前事件完成数累加
//            if (userClinicData.getCurEvenId() > 0) {
//                ClinicEventInfo eventInfo = ClinicMgr.getEventInfo(userClinicData.getCurEvenId());
//                if (eventInfo != null && eventInfo.getDiseaseId() == waitCurePatient.getDiseaseId()) {
//                    userClinicData.setEventCompeteNum(userClinicData.getEventCompeteNum() + 1);
//                }
//            }
            AutoLogMgr.add(cureLog);
        }
        userClinicData.setCuredPatientCount(userClinicData.getCuredPatientCount() + times);
        player.notifyListener(eGamePlayerEventType.ClinicTotalReception.getValue(), userClinicData);
        //领取了
        for (Map.Entry<Integer, DiseaseReward> entry : diseaseRewardMap.entrySet()) {
            DiseaseData diseaseData = userClinicData.getDiseaseDataMap().get(entry.getKey());
            if (diseaseData != null) {
                //增加病症医术值
                diseaseData.setValue(entry.getValue().getValue() + diseaseData.getValue());
            } else {
                logger.info("reward diseaseId no found,userId:{}, diseaseId:{}", getUserId(), entry.getKey());
            }
        }
        userClinicData.setClinicScore(userClinicData.getClinicScore() + recoveryClinicScore);
        player.getModule(CurrencyModule.class).addCurrency(specialRewards, eLogMoneyType.Clinic, eLogMoneyType.ClinicCureReward);
        player.notifyListener(eGamePlayerEventType.ClinicScore.getValue(), userClinicData.getClinicScore());

        changeClinicValueRank();
        syncClinicData();
        ClinicRewardData clinicRewardData = new ClinicRewardData();
        clinicRewardData.setClinicScore(recoveryClinicScore);
        clinicRewardData.setDiseaseRewardMap(diseaseRewardMap);
        clinicRewardData.setReward(specialRewards);
        clinicRewardData.setRewardNum(times);

        ClinicPb.parseClinicReward(clinicRewardData, builder);
        builder.setRet(0);
        return builder;
    }

    /**
     * 获取最大体力恢复上线
     * 找回奖励用
     */
    public int getMaxPower() {
        int patientMax = (int) (userClinicData.getClinicScore() / GameConfig.CLINIC_PATIENT_LIMIT_ADD_SCORE + GameConfig.CLINIC_PATIENT_INIT_LIMIT);
        patientMax = Math.min(patientMax, GameConfig.CLINIC_PATIENT_FINAL_LIMIT);
        return patientMax;
    }

    public int getLastSaveTimePatient() {
        return lastSaveTimePatient;
    }
}
